# @Time : 2024-11-15 15:19
# @Author : Fioman 
# @Phone : 13149920693
"""
处理从UI界面发送的请求,主要是一些按钮的点击,主要是这个类来响应.
"""
import settings
from db_tools.db_handler import DbHandler
from eap_control import eap_request, response_parse
from eap_control.data_model import ClockType
from eap_control.data_model import DataResult
from eap_control.eap_config import EapConfig
from eap_control.eap_debug import debug_eap, log_init
import os
import shutil
from tkinter import Tk, filedialog
from tools.send_to_ui_tools import update_lot_command_download_to_ui, update_prodinfo_download_to_ui

ec = EapConfig()
db = DbHandler()



class EapRequestFromUI:
    @staticmethod
    def web_request_save_eap_config_params(eapConfigParams):
        """
        界面上点击了保存EapConfigParams按钮
        @param eapConfigParams:
        @return:
        """
        res, info = db.save_eap_config_params(eapConfigParams)

        cimModeNew = eapConfigParams.get("cim_mode")
        cimModeIsChanged = eapConfigParams.get("cim_mode") != ec.cimMode
        if res == "ok":
            if cimModeIsChanged:
                # 如果模式发生了变化,延迟导入,防止发生循环引用.如何避免循环引用呢
                resp = eap_request.request_cim_mode_change_report(cimModeNew)
                result = response_parse.parse_cim_mode_report_response(resp)
                if not result.state and cimModeNew == "Remote":
                    newData = {
                        "cim_mode": "Local",
                    }
                    db.save_eap_config_params(newData)
                    debug_eap(result.info)
                    return "error", result.info
            ec.reaload_eap_config_params(sendToUi=True)
        return res, ""

    @staticmethod
    def web_request_save_eap_config_params_extend(eapConfigParams):
        """
        界面上点击了,另外保存eap参数的按钮,保存的是另外一组值
        @param eapConfigParams:
        @return:
        """
        res, info = db.save_eap_config_params(eapConfigParams)
        if res == "ok":
            ec.reaload_eap_config_params(sendToUi=True)
        return res

    @staticmethod
    def ui_btn_param_verify_reqeust(verifyLotId):
        """
        界面上点击了ParamVerify,来验证 固定lotId的制程参数
        @return:
        """
        response = eap_request.request_param_verify(verifyLotId)
        data = response_parse.parse_param_verify_response(response)
        return [data]

    def ui_btn_manual_finish(self, searchId):
        """
        界面上点击了ManualFinish按钮,来手动完成
        @return:
        """
        try:
            dataResult = DataResult()
            debug_eap(f"界面上点击了手动结批按钮要结批的order_id: {searchId}")
            # 1. 执行手动结批的逻辑,将LotCommand中的第一个工单删除掉,删除指定的工单
            res, data = db.get_lot_command_download_info()
            if res == "ok":
                if data:
                    lotCommand = data[0]
                    lotId = lotCommand.get("lot_id")
                    isFirstLot = True if lotId == searchId else False
                    if not isFirstLot:
                        # 如果searchId和lotId不一致,则进行删除其他的工单
                        lotCommandList = [lotCommand for lotCommand in data if lotCommand.get("lot_id") == searchId]
                        if lotCommandList:
                            lotCommand = lotCommandList[0]
                        else:
                            dataResult.state = False
                            dataResult.info = f"手动结批失败,要结批的工单{searchId}不存在"
                            debug_eap(dataResult.info)
                            return dataResult
                    key = lotCommand.get("key")
                    # 2. 删除这个工单
                    query = {
                        "key": key
                    }
                    db.delete_lot_command_download(query)
                    ec.lotId = lotId
                    ec.prodId = lotCommand.get("prod_id")
                    ec.lotQty = lotCommand.get("lot_qty")
                    ec.prodHeight = lotCommand.get("height")
                    ec.prodWidth = lotCommand.get("width")
                    ec.prodCropThickness = lotCommand.get("cropperThick")
                    eap_request.request_wip_tracking_report()
                    # 3. 结批成功之后,执行切换到下一个工单的逻辑
                    if isFirstLot:
                        self.change_lot_command_task()
                        debug_eap(f"手动结批成功,被结批的批号: {lotId},上报WIPTrackingReport成功,要结批的是第一个工单,进行自动工单切换")
                    else:
                        debug_eap(f"手动结批成功,被结批的批号: {lotId},上报WIPTrackingReport成功,但是不是第一个工单,不进行自动工单切换")
                    # 4. 更新当前的工单信息
                    update_lot_command_download_to_ui()
                    ec.reload_prod_lot_list()
                    dataResult.state = True
                    return dataResult
                else:
                    dataResult.state = False
                    dataResult.info = "手动结批失败,要结批的工单队列为空"
                    debug_eap(dataResult.info)
                    return dataResult
            else:
                dataResult.state = False
                dataResult.info = f"手动结批失败,获取工单失败,{data}"
                debug_eap(dataResult.info)
                return dataResult
        except Exception as e:
            dataResult.state = False
            dataResult.info = f"手动结批失败,错误信息: {str(e)}"
            debug_eap(dataResult.info)
            return dataResult

    def change_lot_command_task(self):
        """
        切换到下一个工单
        """
        settings.eapCanChangeOrderFlag = True
        ec.reload_prod_lot_list()

    @staticmethod
    def ui_btn_user_verify_request(payload):
        """
        界面上点击了UserVerify按钮,可能是登录,登出,或者是查询
        :@param 前端界面传递过来的参数
        @return:
        """

        verify_user_id, clock_type = payload
        if clock_type == "ClockIn":
            clock_type = ClockType.I.name
        elif clock_type == "ClockOut":
            clock_type = ClockType.O.name
        else:
            clock_type = ClockType.Q.name
        response = eap_request.request_user_verify(verify_user_id, clock_type)
        result = response_parse.parse_user_verify_response(verify_user_id, clock_type, response)
        return result

    @staticmethod
    def ui_btn_mock_request_click(requestMethod):
        result = None
        if requestMethod == "WIPTrackingReport":
            response = eap_request.request_wip_tracking_report()
            result = response_parse.parse_wip_tracking_response(response)
        elif requestMethod == "UtilityReport":
            response = eap_request.request_utility_report()
            result = response_parse.parse_utility_response(response)
        elif requestMethod == "EquipmentCurrentLotReport":
            response = eap_request.request_eqp_current_lot_report()
            result = response_parse.parse_eqp_current_lot_report(response)
        else:
            debug_eap(f"未处理的请求: {requestMethod}")

        if result is not None and not result.state:
            debug_eap(result.info)

    @staticmethod
    def web_request_save_current_eap_log_to_dir(saveDirPath: str):
        """
        将当前最新的 EAP 日志文件复制到指定目录
        @param saveDirPath: 目标保存目录
        @return: ["ok"] 或者 ["error", 错误信息]
        """
        try:
            if not isinstance(saveDirPath, str) or len(saveDirPath.strip()) == 0:
                return ["error", "保存目录不能为空"]

            targetDir = os.path.abspath(saveDirPath)
            if not os.path.exists(targetDir):
                os.makedirs(targetDir)

            # 从 EAP_DEBUG_DIR 中选择最新的日志文件（按修改时间排序）
            debugDir = settings.EAP_DEBUG_DIR
            if not os.path.exists(debugDir):
                return ["error", f"Eap日志目录不存在: {debugDir}"]

            candidates = []
            for root, dirs, files in os.walk(debugDir):
                for file in files:
                    if root != debugDir:
                        continue
                    if file.endswith(".txt") and settings.PROJECT_NAME in file:
                        filePath = os.path.join(root, file)
                        candidates.append((filePath, os.path.getmtime(filePath)))

            if len(candidates) == 0:
                return ["error", "未找到任何Eap日志文件"]

            latestFilePath, _ = sorted(candidates, key=lambda x: x[1], reverse=True)[0]
            destPath = os.path.join(targetDir, os.path.basename(latestFilePath))
            shutil.copy2(latestFilePath, destPath)
            return ["ok"]
        except Exception as e:
            err = f"in web_request_save_current_eap_log_to_dir() error: {str(e)}"
            debug_eap(err)
            return ["error", err]

    @staticmethod
    def web_request_clear_production_info_download():
        """
        清空 Production Info Download 数据表中的所有数据
        @return: ["ok"] 或者 ["error", 错误信息]
        """
        try:
            res, info = db.delete_download_info(query={})
            if res == "ok":
                update_prodinfo_download_to_ui()
                debug_eap("清空 Production Info Download 数据表成功")
                return ["ok"]
            else:
                err = f"清空 Production Info Download 数据表失败: {info}"
                debug_eap(err)
                return ["error", err]
        except Exception as e:
            err = f"in web_request_clear_production_info_download() error: {str(e)}"
            debug_eap(err)
            return ["error", err]

    @staticmethod
    def web_request_choose_directory():
        """
        打开系统目录选择器,返回选中的目录路径
        :return: ["ok", dirPath] 或 ["error", info]
        """
        result  = DataResult()
        try:
            root = Tk()
            root.withdraw()
            root.attributes('-topmost', True)
            dir_path = filedialog.askdirectory()
            root.destroy()
            if dir_path is None or dir_path == "":
                result.state = False
                result.info = "未选择目录"
                return result
            # 选择成功之后要更新到数据库,并且更新到前端那里当前EapDebug路径上
            query = {
                "key": "1"
            }
            newValues = {
                "$set": {
                    "eapLogDir": dir_path
                }
            }
            db.update_data(db.eap_config_params, query, newValues)
            ec.reaload_eap_config_params(sendToUi=True)
            log_init(changeEapDir=True)
            result.state = True
            return result
        except Exception as e:
            result.state = False
            result.info = str(e)
            return result
